package com.example.petplanet.service;


import com.alibaba.fastjson.JSON;
import com.example.petplanet.domain.*;
import com.example.petplanet.mapper.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class SyncDataService {
    private final StringRedisTemplate stringRedisTemplate;
    private final ContentDao contentDao;
    private final LikeContentDao likeContentDao;
    private final ShareService shareService;
    private final LikeCommentDao likeCommentDao;
    private final CommentDao commentDao;
    private final MarkBookDao markBookDao;




    @Autowired
    private RedissonClient redissonClient;


    @Autowired
    public SyncDataService(StringRedisTemplate stringRedisTemplate, LikeContentDao likeContentDao, ContentDao contentDao, ShareService shareService, LikeCommentDao likeCommentDao, CommentDao commentDao, MarkBookDao markBookDao) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.likeContentDao = likeContentDao;
        this.contentDao = contentDao;
        this.shareService = shareService;
        this.likeCommentDao = likeCommentDao;
        this.commentDao = commentDao;
        this.markBookDao = markBookDao;
    }



    @Transactional
    @Scheduled(cron = "0 0 */6 * * ?") // 每6小时执行一次
//    @Scheduled(cron = "0 */3 * * * ?") // 每6小时执行一次
    public void syncDataRedisToMysql() {
        RLock syncLock = redissonClient.getLock("isSyncing");
        int maxAttempts = 10; // 最大尝试次数
        int attempt = 0;
        while (attempt < maxAttempts) {
            try {
                // 尝试获取锁，等待时间10秒，锁的过期时间15分钟
                if (syncLock.tryLock(10,900, TimeUnit.SECONDS)) {
                    try {
                        syncFollowMarkFromRedisToMysql();
                        syncLikeContentFromRedisToMysql();
                        syncLikeCommentFromRedisToMysql();
                        //同步完成退出，finally仍会执行
                        return;
                    } finally {
                        syncLock.unlock(); // 释放锁
                    }
                } else {
                    attempt++;
                    Thread.sleep(5000); // 等待5秒后再次尝试
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }



    //后期keys换成scan方法
    //关注收藏
    public void syncFollowMarkFromRedisToMysql() {
        Set<Long> toDeleteMarkBookIds = shareService.getToDeleteMarkBookIds();
        try {
            Set<String> keys = stringRedisTemplate.keys("app:user:*");
            if (keys.isEmpty()) return;
            if(toDeleteMarkBookIds.isEmpty()){
                for (String key : keys) {
                    Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
                    String userJson= (String) userMap.get("user");
                    User user = JSON.parseObject(userJson, User.class);
                    //关注同步
                    shareService.syncUserFollow(user);
                    //同步收藏
                    shareService.syncUserMarkBook(user);
                }
            }
            else {
                for (String key : keys) {
                    Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key);
                    String userJson= (String) userMap.get("user");
                    User user = JSON.parseObject(userJson, User.class);
                    //删除已删除的帖子的收藏记录
                    boolean remove = user.getMarkBooks().removeAll(toDeleteMarkBookIds);
                    if(remove) shareService.updateUserRedis(user);
                    //关注同步
                    shareService.syncUserFollow(user);
                    //同步收藏
                    shareService.syncUserMarkBook(user);
                }
                //清空
                shareService.emptyToDeleteMarkBookIds();
            }
            Set<Long> userIds = shareService.getToUpdateLikeMarkUsers();
            for (Long userId : userIds) {
                if(!shareService.judgeUserExistsRedis(userId)) continue;
                User user = shareService.getUserByIdRedis(userId);
                user.setUserLikes(likeContentDao.getLikesByUserId(userId));
                user.setUserTotalBookmarkCount(markBookDao.getMarkCountByUserId(userId));
                shareService.updateUserRedis(user);
            }
            //清空
            shareService.emptyToUpdateLikeMarkUsers();;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    //直接批量操作，因为用户的redis中的数据大部分会插入到mysql中，不需要去除交集部分
    //点赞帖子
    public void syncLikeContentFromRedisToMysql() {
        Set<String> keys = stringRedisTemplate.keys("app:like:content:*:*:*");
        if (keys.isEmpty())  return;
        List<LikeContent> likeContentsToUpdate = new ArrayList<>();
        for (String key : keys) {
            String value=stringRedisTemplate.opsForValue().get(key);
            String[] parts = key.split(":");
            Long userId = Long.parseLong(parts[3]);
            Long contentId = Long.parseLong(parts[4]);
            Long targetId = Long.parseLong(parts[5]);
            boolean status=Boolean.parseBoolean(value);

            LikeContent likeContent=new LikeContent();
            likeContent.setUserId(userId);
            likeContent.setContentId(contentId);
            likeContent.setTargetId(targetId);
            likeContent.setStatus(status);
            likeContentsToUpdate.add(likeContent);
        }
        likeContentDao.batchInsertLikeContent(likeContentsToUpdate);
        //点赞数同步
        syncLikeContentCountFromRedisToMysql();
    }


    //子方法，点赞帖子数
    public void syncLikeContentCountFromRedisToMysql() {
        Set<String> keys = stringRedisTemplate.keys("app:likeCount:content:*");
        // 收集所有需要同步的数据
        List<Content> contentsToUpdate = new ArrayList<>();
        if (keys.isEmpty()) return;
        for (String key : keys) {
            // 获取内容 ID
            Long contentId = Long.parseLong(key.split(":")[3]);
            // 获取 Redis 中的点赞数
            String likeCountStr = stringRedisTemplate.opsForValue().get(key);
            Long likeCount = Long.parseLong(likeCountStr);
            // 创建或更新内容对象
            Content content = new Content();
            content.setContentId(contentId);
            content.setGood(likeCount);
            contentsToUpdate.add(content);
        }
        // 批量更新 MySQL 中的数据
        contentDao.batchUpdateContentGoodCount(contentsToUpdate);
    }



    //点赞评论
    public void syncLikeCommentFromRedisToMysql() {
        Set<String> keys = stringRedisTemplate.keys("app:like:comment:*:*");
        if (keys.isEmpty()) return;
        List<LikeComment> likeCommentsToUpdate = new ArrayList<>();
        for (String key : keys) {
            String value=stringRedisTemplate.opsForValue().get(key);
            String[] parts = key.split(":");
            Long userId = Long.parseLong(parts[3]);
            Long commentId = Long.parseLong(parts[4]);
            boolean status=Boolean.parseBoolean(value);
            LikeComment likeComment=new LikeComment();
            likeComment.setUserId(userId);
            likeComment.setCommentId(commentId);
            likeComment.setStatus(status);
            likeCommentsToUpdate.add(likeComment);
        }
        likeCommentDao.batchInsertLikeComment(likeCommentsToUpdate);
        syncLikeCommentCountFromRedisToMysql();
    }


    //子方法，点赞评论数
    public void syncLikeCommentCountFromRedisToMysql() {
        Set<String> keys = stringRedisTemplate.keys("app:likeCount:comment:*");
        // 收集所有需要同步的数据
        List<Comment> commentsToUpdate = new ArrayList<>();
        if (keys.isEmpty()) return;
        for (String key : keys) {
            // 获取内容 ID
            Long commentId = Long.parseLong(key.split(":")[3]);
            // 获取 Redis 中的评论点赞数
            String likeCountStr = stringRedisTemplate.opsForValue().get(key);
            Long likeCount = Long.parseLong(likeCountStr);
            // 创建或更新内容对象
            Comment comment = new Comment();
            comment.setCommentId(commentId);
            comment.setGood(likeCount);
            commentsToUpdate.add(comment);
        }
        // 批量更新 MySQL 中的数据
        commentDao.batchUpdateCommentGoodCount(commentsToUpdate);
    }

}
